/*
 * 
 */
package com.oniontech.stamptour.resuorce;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Hashtable;

import com.oniontech.stamptour.common.lang.LOG;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.NinePatch;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.NinePatchDrawable;

// TODO: Auto-generated Javadoc
/**
 * �̹���(Bitamp) �� class �̱��� ��ü<br>
 * �̹����� �ҷ����鼭 ���ο� �����Ͽ� ������ ȿ���� ���δ�.
 * 
 * @author limsy
 * @since 2013/02/04
 * 
 */
public class BitmapManager
{

	/**
	 * ��.
	 */
	private BitmapManager()
	{
		bitmapTable = new Hashtable<String, Bitmap>();

	}

	/**
	 * �� �� ��ü�� Instance�� ��ȯ�Ѵ�.
	 * 
	 * @return BitmapManager ��ü
	 */
	public static BitmapManager getInstance()
	{
		if (Instance == null)
		{
			Instance = new BitmapManager();
		}
		return Instance;
	}

	/**
	 * Application Context ��ü�� �ʱ�ȭ �Ѵ�.
	 * 
	 * @param context
	 *            Application Context ��ü
	 */
	public void setContext(Context context)
	{
		m_Context = context;
	}

	/**
	 * ���� ���ҽ��� ���Ե� Image(Bitamp)��ü�� ��´�.
	 * 
	 * @param resId
	 *            ���ҽ� ID
	 * @return Bitmap ��ü
	 */
	public Bitmap getBitmap(int resId)
	{
		Bitmap bitmap = null;

		String key = m_Context.getString(resId);
		LOG.Log_DEV(TAG, "Resource ID : " + resId + ", path : " + key);
		if (!bitmapTable.containsKey(key))
		{
			bitmap = BitmapFactory.decodeResource(m_Context.getResources(),
					resId);
			bitmapTable.put(key, bitmap);
		} else
		{
			bitmapTable.get(key);
		}
		return getBitmap(m_Context.getString(resId));
	}

	/**
	 * bitmap �� drawable �� ��´�.
	 * 
	 * @param bitmap
	 *            the bitmap
	 * @return drawable
	 */
	public Drawable getDrawable(Bitmap bitmap)
	{
		return new BitmapDrawable(bitmap);
	}

	/**
	 * �ܺ� ���ҽ�(SDCard) Image(Bitmap)��ü�� ��´�.
	 * 
	 * @param path
	 *            Image���� path
	 * @return Bitmap ��ü
	 */
	public Bitmap getBitmap(String path)
	{
		Bitmap bitmap = null;

		if (!bitmapTable.containsKey(path))
		{
			LOG.Log_DEV(TAG, "Resource PATH : " + path);
			// BitmapFactory.Options bmOptions = new BitmapFactory.Options();
			// bmOptions.inSampleSize = 2;
			// bitmap = BitmapFactory.decodeFile(path, bmOptions);

			// Find the correct scale value. It should be the power of 2.
			int scale = 1;
			// decode with inSampleSize
			BitmapFactory.Options o2 = new BitmapFactory.Options();
			o2.inPreferredConfig = Config.RGB_565;
			o2.inSampleSize = scale;
			bitmap = BitmapFactory.decodeFile(path, o2);

			if (bitmap == null)
			{
				LOG.Log_DEV(TAG, "Resource Load Fail ~~~!! PATH : " + path);
				return null;
			}
			bitmapTable.put(path, bitmap);
		} else
		{
			bitmap = bitmapTable.get(path);
		}
		return bitmap;
	}

	/**
	 * ���� ���ҽ��� ���Ե� Image(Bitamp)��ü�� �迭�� ��´�.
	 * 
	 * @param id
	 *            ���ҽ� ID�迭
	 * @return Bitmap ��ü �迭
	 */
	public Bitmap[] getBitmap(int[] id)
	{
		Bitmap[] bitmap = new Bitmap[id.length];
		for (int i = 0; i < id.length; i++)
		{
			bitmap[i] = getBitmap(id[i]);
		}
		return bitmap;
	}

	/**
	 * ��Ʈ��ũ(web) ���� Image(Bitamp)��ü�� ��´�.
	 * 
	 * @param url
	 *            ���ҽ� url
	 * @return Bitmap ��ü
	 * @throws IOException
	 *             Signals that an I/O exception has occurred.
	 */
	public Bitmap getBitmap(URL url) throws IOException
	{
		Bitmap map = null;
		String key = url.toString();
		LOG.Log_DEV(TAG, "Bitmap URL : " + key);
		if (!bitmapTable.containsKey(key))
		{
			URLConnection connect = url.openConnection();
			connect.connect();

			InputStream is = connect.getInputStream();
			map = BitmapFactory.decodeStream(is);
			if (map == null)
			{
				LOG.Log_DEV(TAG, "Resource Load Fail ~~~!! PATH : " + key);
				return null;
			}
			bitmapTable.put(key, map);
		} else
		{
			map = bitmapTable.get(key);
		}
		return map;
	}

	/**
	 * �ܺ� ���ҽ�(SDCard) Image(Bitmap)��ü�� �뷮(ȭ��)�� ���缭 ��´�.
	 * 
	 * @param path
	 *            Image���� path
	 * @param simple
	 *            ��� ����
	 * @return Bitmap ��ü
	 */
	public Bitmap getBitmap(String path, int simple)
	{
		Bitmap map = null;
		if (!bitmapTable.containsKey(path))
		{
			LOG.Log_DEV(TAG, "Resource PATH : " + path);
			BitmapFactory.Options option = new BitmapFactory.Options();
			option.inSampleSize = simple;
			map = BitmapFactory.decodeFile(path, option);
			bitmapTable.put(path, map);
		} else
		{
			map = bitmapTable.get(path);
		}
		return map;

	}

	/**
	 * ���� ���ҽ��� ���Ե� Image(Bitamp)��ü�� Ÿ�ϸ� �Ͽ� ��´�.
	 * 
	 * @param resId
	 *            ���ҽ� ID
	 * @param widthlen
	 *            �ڸ� ����
	 * @param heightlen
	 *            �ڸ� ����
	 * @return Bitmap ��ü �迭
	 */
	public Bitmap[] getTempBitmap(int resId, int widthlen, int heightlen)
	{
		return getTempBitmap(getBitmap(resId), widthlen, heightlen);
	}

	/**
	 * Bitmap ��ü�� Ÿ�ϸ� �Ͽ� ��´�.
	 * 
	 * @param res
	 *            Bitmap ��
	 * @param widthlen
	 *            �ڸ� ����
	 * @param heightlen
	 *            �ڸ� ����
	 * @return Bitmap ��ü �迭
	 */
	public Bitmap[] getTempBitmap(Bitmap res, int widthlen, int heightlen)
	{
		int lenth = widthlen * heightlen;
		Bitmap[] bitmap = new Bitmap[lenth];
		int width = res.getWidth() / widthlen;
		int height = res.getHeight() / heightlen;
		for (int i = 0, x = 0, y = 0; i < lenth; i++)
		{
			x = (i % widthlen) * width;
			y = (i / widthlen) * height;
			bitmap[i] = Bitmap.createBitmap(res, x, y, width, height);
		}
		return bitmap;
	}

	/**
	 * ���� ���ҽ��� ���Ե� Image(Bitmap)��ü�� �ش� ���� ��ŭ �߶� ��´�.
	 * 
	 * @param resId
	 *            ���ҽ� ID
	 * @param width
	 *            �ڸ� ����
	 * @param height
	 *            �ڸ� ����
	 * @return Bitmap ��ü
	 */
	public Bitmap getCropBitmap(int resId, int width, int height)
	{
		return getCropBitmap(getBitmap(resId), width, height);
	}

	/**
	 * Bitamp ��ü�� �ش� ���� ��ŭ �߶� ��´�.
	 * 
	 * @param res
	 *            Bitmap ��ü
	 * @param width
	 *            �ڸ� ����
	 * @param height
	 *            �ڸ� ����
	 * @return Bitmap ��ü
	 */
	public Bitmap getCropBitmap(Bitmap res, int width, int height)
	{
		return Bitmap.createBitmap(res, 0, 0, width, height);
	}

	/**
	 * �̹��� ����� Ȯ�� �Ǵ� ��� ��Ų��.
	 * 
	 * @param path
	 *            �̹��� ���
	 * @param scale
	 *            Ȯ�� ��� ����
	 * @return ��Ʈ�� ��ü
	 */
	public Bitmap getSmallResizeBitmap(String path, int scale)
	{
		Options option = new Options();
		option.inSampleSize = scale;
		return BitmapFactory.decodeFile(path, option);
	}

	/**
	 * �̹��� ����� Ȯ�� �Ǵ� ��� ��Ų�� �� ���ο� �������� �ʴ´�.
	 * 
	 * @param path
	 *            �̹��� ���.
	 * @param width
	 *            �̹��� ����.
	 * @param height
	 *            �̹��� ����.
	 * @return ��Ʈ�� ��ü
	 */
	public Bitmap getTempResizeBitmap(String path, int width, int height)
	{
		return Bitmap.createScaledBitmap(getBitmap(path), width, height, true);
	}

	/**
	 * �̹��� ����� �뷮 �� Ȯ�� �Ǵ� ��� ��Ų��. �� ���ο� �������� �ʴ´�.
	 * 
	 * @param path
	 *            �̹��� ���.
	 * @param option
	 *            �뷮 ��� ��.
	 * @param width
	 *            �̹��� ����.
	 * @param height
	 *            �̹��� ����.
	 * @return ��Ʈ�� ��ü.
	 */
	public Bitmap getTempResizeBitmap(String path, int option, int width,
			int height)
	{
		return Bitmap.createScaledBitmap(getBitmap(path, option), width,
				height, true);
	}

	/**
	 * ��Ʈ�� �迭 ��ü �޸� ȯ���Ѵ�.
	 * 
	 * @param bitmap
	 *            ��Ʈ�� �迭 ��ü
	 */
	public void flushBitmap(Bitmap[] bitmap)
	{
		if (bitmap == null)
			return;
		for (int i = 0; i < bitmap.length; i++)
		{
			flushBitmap(bitmap[i]);
		}
		bitmap = null;
	}

	/**
	 * ��Ʈ�� ��ü �޸𸮸� ȯ���Ѵ�.
	 * 
	 * @param bitmap
	 *            ��Ʈ�� ��ü
	 */
	public void flushBitmap(Bitmap bitmap)
	{
		if (bitmap == null)
			return;
		if (bitmapTable.contains(bitmap))
		{
			String[] key = new String[bitmapTable.size()];
			bitmapTable.keySet().toArray(key);
			for (int i = 0; i < key.length; i++)
			{
				if (bitmapTable.get(key[i]).equals(bitmap))
				{
					Bitmap map = bitmapTable.remove(key[i]);
					map.recycle();
					map = null;
					return;
				}
			}
		}
		bitmap.recycle();
		bitmap = null;
	}

	/**
	 * ���θ��ҽ� ��Ʈ�� ��ü �޸𸮸� ȯ���Ѵ�.
	 * 
	 * @param resId
	 *            ���θ��ҽ� Id �迭
	 */
	public void flushBitmap(int[] resId)
	{
		for (int i = 0; i < resId.length; i++)
		{
			flushBitmap(resId[i]);
		}
	}

	/**
	 * ���θ��ҽ� ��Ʈ�� ��ü �޸𸮸� ȯ���Ѵ�.
	 * 
	 * @param resId
	 *            ���θ��ҽ� id
	 */
	public void flushBitmap(int resId)
	{
		String key = m_Context.getString(resId);
		flushBitmap(key);
	}

	/**
	 * �ܺθ��ҽ� ��Ʈ�� ��ü �޸𸮸� ȯ���Ѵ�.
	 * 
	 * @param keys
	 *            ����Path �迭
	 */
	public void flushBitmap(String[] keys)
	{
		for (int i = 0, n = keys.length; i < n; i++)
		{
			flushBitmap(keys[i]);
		}
	}

	/**
	 * �ܺθ��ҽ� ��Ʈ�� ��ü �޸𸮸� ȯ���Ѵ�.
	 * 
	 * @param key
	 *            ���� path
	 */
	public void flushBitmap(String key)
	{
		if (bitmapTable.containsKey(key))
		{
			Bitmap map = bitmapTable.remove(key);
			map.recycle();
			map = null;
		}
	}

	/**
	 * ���ο� ����� ��Ʈ�ʰ�ü ��� �޸𸮸� ȯ���Ѵ�.
	 */
	public void flushAll()
	{
		String[] keys = new String[bitmapTable.size()];
		bitmapTable.keySet().toArray(keys);
		flushBitmap(keys);
		keys = null;
		bitmapTable.clear();
	}

	/**
	 * �̹��� �� class �޸𸮸� ȯ���Ѵ�.
	 */
	public void destory()
	{
		flushAll();
		bitmapTable = null;
		m_Context = null;
		Instance = null;
	}

	/**
	 * Sets the ninepatch.
	 * 
	 * @param byt
	 *            the byt
	 * @return the nine patch drawable
	 */
	public NinePatchDrawable setNinepatch(byte[] byt)
	{

		NinePatchDrawable np = null;
		Bitmap bitmp = BitmapFactory.decodeByteArray(byt, 0, byt.length);
		NinePatch npemp = new NinePatch(bitmp, bitmp.getNinePatchChunk(), null);
		np = new NinePatchDrawable(npemp);

		return np;

	}

	/** LOG �� �ʿ��� TAG ���� ���� �� �ʱ�ȭ. */
	private static final String TAG = BitmapManager.class.getSimpleName();

	/** �̹��� �� ��ü Instance ���� ����. */
	private static BitmapManager Instance;

	/** ���ο� ������ ��ü ���� ����. */
	private Hashtable<String, Bitmap> bitmapTable;

	/** Application Context ���� ����. */
	private Context m_Context;
}
